package cn.fan.study.eight.netty;

import cn.fan.study.eight.coder.NettyMessageDecoder;
import cn.fan.study.eight.coder.NettyMessageEncoder;
import cn.fan.study.eight.handler.HeartBeatRespHandler;
import cn.fan.study.eight.handler.LoginAuthRespHandler;
import cn.fan.study.eight.handler.ServerHandler;
import cn.fan.study.eight.message.NettyConstant;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;

import java.io.IOException;

public class NettyServer {

    public void bind() throws Exception {
        // 配置服务端的NIO线程组  
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100)
//                    .handler(new LoggingHandler(LogLevel.INFO))
//                    不设置的话，客户端会掉线然后ip端口就被占用了
                    .option(ChannelOption.SO_RCVBUF, 32*1024)	// 设置接受数据的缓存大小
                    .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)	// 设置保持连接
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws IOException {
                            ch.pipeline().addLast(new NettyMessageDecoder(1024 * 1024, 4, 4));
                            ch.pipeline().addLast(new NettyMessageEncoder());
                            ch.pipeline().addLast("readTimeoutHandler", new ReadTimeoutHandler(50));
                            ch.pipeline().addLast(new LoginAuthRespHandler());
                            ch.pipeline().addLast("HeartBeatHandler", new HeartBeatRespHandler());
//                            业务实现
                            ch.pipeline().addLast(new ServerHandler());
                        }
                    });

            // 绑定端口，同步等待成功  
            ChannelFuture f = b.bind(NettyConstant.REMOTEIP, NettyConstant.PORT).sync();
            System.out.println("Netty server start ok : " + (NettyConstant.REMOTEIP + " : " + NettyConstant.PORT));
            // 等待服务端监听端口关闭  
            f.channel().closeFuture().sync();


            // 绑定端口，同步等待成功  
            //b.bind(NettyConstant.REMOTEIP, NettyConstant.PORT).sync();  
            //System.out.println("Netty server start ok : " + (NettyConstant.REMOTEIP + " : " + NettyConstant.PORT));  
        } finally {
            // 优雅退出，释放线程池资源  
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        new NettyServer().bind();
    }

}  